{% extends "base.html" %}

{% block title %}{{ graph.title }} - 知识图谱系统{% endblock %}

{% block content %}
<div class="row g-0">
    <!-- 控制面板 -->
    <div class="col-md-3 col-lg-2">
        <div class="control-panel bg-light border-end" style="min-height: calc(100vh - 120px);">
            <div class="p-3">
                <h6 class="mb-3">{{ graph.title }}</h6>
                <p class="text-muted small">{{ graph.description or '暂无描述' }}</p>

                <!-- 搜索功能 -->
                <div class="mb-3">
                    <label class="form-label small">搜索节点</label>
                    <input type="text" class="form-control form-control-sm" id="searchInput"
                           placeholder="输入节点名称">
                </div>

                <!-- 控制选项 -->
                <div class="mb-3">
                    <div class="form-check form-switch">
                        <input class="form-check-input" type="checkbox" id="showLabels" checked>
                        <label class="form-check-label small" for="showLabels">显示标签</label>
                    </div>
                    <div class="form-check form-switch">
                        <input class="form-check-input" type="checkbox" id="showEdges" checked>
                        <label class="form-check-label small" for="showEdges">显示连线</label>
                    </div>
                </div>

                <!-- 力导向强度 -->
                <div class="mb-3">
                    <label class="form-label small">力导向强度</label>
                    <input type="range" class="form-range" id="forceStrength"
                           min="-100" max="100" value="0">
                </div>

                <!-- 统计信息 -->
                <div class="mb-3">
                    <h6 class="small">统计信息</h6>
                    <div class="stats small text-muted">
                        <div>节点数: <span id="nodeCount">0</span></div>
                        <div>连线数: <span id="edgeCount">0</span></div>
                    </div>
                </div>

                <!-- 操作按钮 -->
                <div class="d-grid gap-2">
                    <button class="btn btn-sm btn-outline-primary" onclick="resetView()">
                        <i class="fas fa-undo me-1"></i>重置视图
                    </button>
                    {% if can_download %}
                    <div class="btn-group">
                        <button type="button" class="btn btn-sm btn-success dropdown-toggle"
                                data-bs-toggle="dropdown">
                            <i class="fas fa-download me-1"></i>下载
                        </button>
                        <ul class="dropdown-menu">
                            <li><a class="dropdown-item" href="#" onclick="downloadGraph('png')">
                                <i class="fas fa-image me-2"></i>PNG格式
                            </a></li>
                            <li><a class="dropdown-item" href="#" onclick="downloadGraph('jpg')">
                                <i class="fas fa-image me-2"></i>JPG格式
                            </a></li>
                        </ul>
                    </div>
                    {% endif %}
                </div>
            </div>
        </div>
    </div>

    <!-- 图谱显示区域 -->
    <div class="col-md-9 col-lg-10">
        <div class="graph-container position-relative">
            <svg id="graph-svg" width="100%" height="100%"></svg>

            <!-- 加载指示器 -->
            <div id="loading" class="position-absolute top-50 start-50 translate-middle">
                <div class="text-center">
                    <div class="spinner-border text-primary" role="status">
                        <span class="visually-hidden">加载中...</span>
                    </div>
                    <div class="mt-2">正在加载图谱数据...</div>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- 节点详情模态框 -->
<div class="modal fade" id="nodeModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="nodeModalTitle">节点详情</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div class="row">
                    <div class="col-md-6">
                        <button class="btn btn-primary w-100 mb-3" onclick="getNodeDetails()">
                            <i class="fas fa-info-circle me-2"></i>获取详情信息
                        </button>
                        <div id="nodeDetails" class="border rounded p-3 bg-light">
                            <p class="text-muted">点击上方按钮获取AI生成的详细信息</p>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <button class="btn btn-warning w-100 mb-3" onclick="getNodeQuiz()">
                            <i class="fas fa-question-circle me-2"></i>生成测试题目
                        </button>
                        <div id="nodeQuiz" class="border rounded p-3 bg-light">
                            <p class="text-muted">点击上方按钮生成相关测试题目</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- 测试题目模态框 -->
<div class="modal fade" id="quizModal" tabindex="-1">
    <div class="modal-dialog modal-xl">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">知识测试</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div id="quizContent"></div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                <button type="button" class="btn btn-primary" id="submitQuiz" style="display:none;"
                        onclick="submitQuiz()">提交答案</button>
            </div>
        </div>
    </div>
</div>
{% endblock %}

{% block head %}
<style>
.graph-container {
    height: calc(100vh - 120px);
    overflow: hidden;
}

.control-panel {
    overflow-y: auto;
}

.node {
    cursor: pointer;
    stroke: #fff;
    stroke-width: 2px;
}

.node:hover {
    stroke-width: 3px;
}

.link {
    stroke: #999;
    stroke-opacity: 0.6;
    stroke-width: 2px;
}

.node-label {
    font-size: 12px;
    font-weight: bold;
    text-anchor: middle;
    dominant-baseline: middle;
    pointer-events: none;
    fill: #333;
}

.highlighted {
    stroke: #ff6b6b;
    stroke-width: 4px;
}

.stats div {
    padding: 2px 0;
}

.quiz-question {
    margin-bottom: 20px;
    padding: 15px;
    border: 1px solid #ddd;
    border-radius: 5px;
}

.quiz-option {
    margin: 5px 0;
}

.correct-answer {
    background-color: #d4edda;
    border-color: #c3e6cb;
}

.wrong-answer {
    background-color: #f8d7da;
    border-color: #f5c6cb;
}
</style>
{% endblock %}

{% block scripts %}
<script>
let graphData = null;
let simulation = null;
let svg = null;
let g = null;
let currentNode = null;
let currentQuizData = null;

// 颜色方案
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);

// 初始化
document.addEventListener('DOMContentLoaded', function() {
    initializeGraph();
    loadGraphData();
});

function initializeGraph() {
    const container = document.querySelector('.graph-container');
    const width = container.clientWidth;
    const height = container.clientHeight;

    svg = d3.select('#graph-svg')
        .attr('width', width)
        .attr('height', height);

    // 添加缩放功能
    const zoom = d3.zoom()
        .scaleExtent([0.1, 10])
        .on('zoom', function(event) {
            g.attr('transform', event.transform);
        });

    svg.call(zoom);

    // 创建主要绘图组
    g = svg.append('g');

    // 添加箭头标记
    svg.append('defs').append('marker')
        .attr('id', 'arrowhead')
        .attr('viewBox', '-0 -5 10 10')
        .attr('refX', 20)
        .attr('refY', 0)
        .attr('orient', 'auto')
        .attr('markerWidth', 6)
        .attr('markerHeight', 6)
        .attr('xoverflow', 'visible')
        .append('svg:path')
        .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
        .attr('fill', '#999')
        .style('stroke','none');
}

function loadGraphData() {
    fetch(`/api/graph/{{ graph.id }}/data`)
        .then(response => response.json())
        .then(data => {
            if (data.error) {
                alert('加载失败: ' + data.error);
                return;
            }
            graphData = data;
            updateStats();
            renderGraph();
            document.getElementById('loading').style.display = 'none';
        })
        .catch(error => {
            console.error('Error:', error);
            alert('加载图谱数据失败');
            document.getElementById('loading').style.display = 'none';
        });
}

function updateStats() {
    document.getElementById('nodeCount').textContent = graphData.nodes.length;
    document.getElementById('edgeCount').textContent = graphData.edges.length;
}

function renderGraph() {
    const width = svg.attr('width');
    const height = svg.attr('height');

    // 创建力导向模拟
    simulation = d3.forceSimulation(graphData.nodes)
        .force('link', d3.forceLink(graphData.edges).id(d => d.id).distance(100))
        .force('charge', d3.forceManyBody().strength(-300))
        .force('center', d3.forceCenter(width / 2, height / 2))
        .force('collision', d3.forceCollide().radius(d => (d.size || 20) + 5));

    // 绘制连线
    const link = g.append('g')
        .attr('class', 'links')
        .selectAll('line')
        .data(graphData.edges)
        .enter().append('line')
        .attr('class', 'link')
        .attr('marker-end', 'url(#arrowhead)');

    // 绘制节点
    const node = g.append('g')
        .attr('class', 'nodes')
        .selectAll('circle')
        .data(graphData.nodes)
        .enter().append('circle')
        .attr('class', 'node')
        .attr('r', d => d.size || 20)
        .attr('fill', d => colorScale(d.group || 0))
        .call(d3.drag()
            .on('start', dragstarted)
            .on('drag', dragged)
            .on('end', dragended))
        .on('click', function(event, d) {
            showNodeModal(d);
        })
        .on('mouseover', function(event, d) {
            // 显示工具提示
            d3.select(this).attr('stroke-width', 4);
        })
        .on('mouseout', function(event, d) {
            d3.select(this).attr('stroke-width', 2);
        });

    // 添加节点标签
    const label = g.append('g')
        .attr('class', 'labels')
        .selectAll('text')
        .data(graphData.nodes)
        .enter().append('text')
        .attr('class', 'node-label')
        .text(d => d.label || d.id);

    // 更新位置
    simulation.on('tick', () => {
        link
            .attr('x1', d => d.source.x)
            .attr('y1', d => d.source.y)
            .attr('x2', d => d.target.x)
            .attr('y2', d => d.target.y);

        node
            .attr('cx', d => d.x)
            .attr('cy', d => d.y);

        label
            .attr('x', d => d.x)
            .attr('y', d => d.y);
    });

    // 设置事件监听器
    setupEventListeners();
}

function setupEventListeners() {
    // 搜索功能
    document.getElementById('searchInput').addEventListener('input', function(e) {
        const searchTerm = e.target.value.toLowerCase();

        d3.selectAll('.node')
            .classed('highlighted', false)
            .attr('stroke', '#fff');

        if (searchTerm) {
            d3.selectAll('.node')
                .filter(d => (d.label || d.id).toLowerCase().includes(searchTerm))
                .classed('highlighted', true)
                .attr('stroke', '#ff6b6b');
        }
    });

    // 显示/隐藏标签
    document.getElementById('showLabels').addEventListener('change', function(e) {
        d3.selectAll('.node-label')
            .style('display', e.target.checked ? 'block' : 'none');
    });

    // 显示/隐藏连线
    document.getElementById('showEdges').addEventListener('change', function(e) {
        d3.selectAll('.link')
            .style('display', e.target.checked ? 'block' : 'none');
    });

    // 力导向强度调节
    document.getElementById('forceStrength').addEventListener('input', function(e) {
        const strength = parseInt(e.target.value);
        if (simulation) {
            simulation.force('charge', d3.forceManyBody().strength(strength * -5));
            simulation.alpha(0.3).restart();
        }
    });
}

// 拖拽功能
function dragstarted(event, d) {
    if (!event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
}

function dragged(event, d) {
    d.fx = event.x;
    d.fy = event.y;
}

function dragended(event, d) {
    if (!event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
}

// 重置视图
function resetView() {
    if (simulation) {
        simulation.alpha(0.3).restart();
    }

    // 重置缩放
    svg.transition().duration(750).call(
        d3.zoom().transform,
        d3.zoomIdentity
    );

    // 清除搜索
    document.getElementById('searchInput').value = '';
    d3.selectAll('.node')
        .classed('highlighted', false)
        .attr('stroke', '#fff');
}

// 显示节点模态框
function showNodeModal(node) {
    currentNode = node;
    document.getElementById('nodeModalTitle').textContent = node.label || node.id;
    document.getElementById('nodeDetails').innerHTML = '<p class="text-muted">点击上方按钮获取AI生成的详细信息</p>';
    document.getElementById('nodeQuiz').innerHTML = '<p class="text-muted">点击上方按钮生成相关测试题目</p>';

    const modal = new bootstrap.Modal(document.getElementById('nodeModal'));
    modal.show();
}

// 获取节点详情
function getNodeDetails() {
    if (!currentNode) return;

    const detailsDiv = document.getElementById('nodeDetails');
    detailsDiv.innerHTML = '<div class="text-center"><div class="spinner-border spinner-border-sm" role="status"></div> 正在获取详细信息...</div>';

    fetch(`/api/node/{{ graph.id }}/${currentNode.id}/details`)
        .then(response => response.json())
        .then(data => {
            if (data.error) {
                detailsDiv.innerHTML = `<div class="alert alert-danger">${data.error}</div>`;
                return;
            }
            detailsDiv.innerHTML = `<div class="alert alert-info"><strong>AI生成的详细信息：</strong><br>${data.details}</div>`;
        })
        .catch(error => {
            console.error('Error:', error);
            detailsDiv.innerHTML = '<div class="alert alert-danger">获取详细信息失败</div>';
        });
}

// 获取节点测试题目
function getNodeQuiz() {
    if (!currentNode) return;

    const quizDiv = document.getElementById('nodeQuiz');
    quizDiv.innerHTML = '<div class="text-center"><div class="spinner-border spinner-border-sm" role="status"></div> 正在生成测试题目...</div>';

    fetch(`/api/node/{{ graph.id }}/${currentNode.id}/quiz`)
        .then(response => response.json())
        .then(data => {
            if (data.error) {
                quizDiv.innerHTML = `<div class="alert alert-danger">${data.error}</div>`;
                return;
            }
            currentQuizData = data;
            quizDiv.innerHTML = `
                <div class="alert alert-success">
                    <strong>已生成 ${data.questions.length} 道测试题目</strong><br>
                    <button class="btn btn-sm btn-primary mt-2" onclick="showFullQuiz()">
                        <i class="fas fa-play me-1"></i>开始测试
                    </button>
                </div>
            `;
        })
        .catch(error => {
            console.error('Error:', error);
            quizDiv.innerHTML = '<div class="alert alert-danger">生成测试题目失败</div>';
        });
}

// 显示完整测试
function showFullQuiz() {
    if (!currentQuizData) return;

    const modal = new bootstrap.Modal(document.getElementById('quizModal'));
    const content = document.getElementById('quizContent');

    let html = `<h5>关于"${currentQuizData.node.label}"的知识测试</h5><hr>`;

    currentQuizData.questions.forEach((q, index) => {
        html += `
            <div class="quiz-question" data-question="${index}">
                <h6>第 ${index + 1} 题：${q.question}</h6>
                <div class="options">
        `;

        q.options.forEach((option, optIndex) => {
            html += `
                <div class="quiz-option">
                    <label>
                        <input type="radio" name="q${index}" value="${optIndex}">
                        ${String.fromCharCode(65 + optIndex)}. ${option}
                    </label>
                </div>
            `;
        });

        html += `
                </div>
                <div class="explanation" style="display:none;">
                    <div class="alert alert-info mt-2">
                        <strong>解析：</strong>${q.explanation}
                    </div>
                </div>
            </div>
        `;
    });

    content.innerHTML = html;
    document.getElementById('submitQuiz').style.display = 'inline-block';
    modal.show();
}

// 提交测试答案
function submitQuiz() {
    if (!currentQuizData) return;

    let score = 0;
    const questions = document.querySelectorAll('.quiz-question');

    questions.forEach((questionDiv, index) => {
        const selectedOption = questionDiv.querySelector('input[type="radio"]:checked');
        const question = currentQuizData.questions[index];
        const explanation = questionDiv.querySelector('.explanation');

        if (selectedOption) {
            const answer = parseInt(selectedOption.value);
            if (answer === question.correct) {
                score++;
                questionDiv.classList.add('correct-answer');
            } else {
                questionDiv.classList.add('wrong-answer');
            }
        } else {
            questionDiv.classList.add('wrong-answer');
        }

        explanation.style.display = 'block';
    });

    // 显示结果
    const resultHtml = `
        <div class="alert alert-primary text-center">
            <h5>测试完成！</h5>
            <p>您的得分：${score} / ${currentQuizData.questions.length}</p>
            <p>正确率：${Math.round(score / currentQuizData.questions.length * 100)}%</p>
        </div>
    `;

    document.getElementById('quizContent').insertAdjacentHTML('afterbegin', resultHtml);
    document.getElementById('submitQuiz').style.display = 'none';

    // 滚动到顶部
    document.getElementById('quizModal').querySelector('.modal-body').scrollTop = 0;
}

// 下载图谱
function downloadGraph(format) {
    window.open(`/api/graph/{{ graph.id }}/download/${format}`, '_blank');
}

// 响应式调整
window.addEventListener('resize', function() {
    const container = document.querySelector('.graph-container');
    const width = container.clientWidth;
    const height = container.clientHeight;

    svg.attr('width', width).attr('height', height);

    if (simulation) {
        simulation.force('center', d3.forceCenter(width / 2, height / 2));
        simulation.alpha(0.3).restart();
    }
});
</script>
{% endblock %}